home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 2
/
Atari Mega Archive CD - Volume 2.iso
/
minix
/
up1510b.tgz
/
up1510b
/
src
/
commands
/
mkfs.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-07-23
|
28KB
|
1,221 lines
/* mkfs - make the MINIX filesystem Authors: A. Tanenbaum & P. Ogilvie */
/* Andy Tanenbaum & Paul Ogilvie, June 1986
*
* This program was initially designed to build a filesystem
* with blocksize = zonesize. During the course of time the
* program is being converted to handle zone_size > blocksize
* but this isn't complete yet. Where routines can handle the
* situation this is mentioned in the comment.
*
* To compile this program for MS-DOS, use: cc -DDOS mkfs.c diskio.asm
* To compile this program for UNIX, use: cc -DUNIX mkfs.c
* To compile this program for MINIX, use: cc mkfs.c
*/
#include <sys/types.h>
#include <limits.h>
#include <minix/config.h>
#include <minix/const.h>
#include <minix/type.h>
#include "../fs/const.h"
#undef EXTERN
#define EXTERN /* get rid of EXTERN by making it null */
#include "../fs/type.h"
#include "../fs/super.h"
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#ifndef DOS
#ifndef UNIX
#undef printf /* printf is a macro for printk */
#define UNIX
#endif
#endif
#define INODE_MAP 2
#define MAX_TOKENS 10
#define LINE_LEN 200
#define BIN 2
#define BINGRP 2
#define BIT_MAP_SHIFT 13
#define N_BLOCKS 0x10000L /* must be multiple of 8 */
#ifdef DOS
maybedefine O_RDONLY 4 /* O_RDONLY | BINARY_BIT */
maybedefine BWRITE 5 /* O_WRONLY | BINARY_BIT */
#endif
#if (MACHINE == ATARI)
int isdev;
#endif
int next_zone, next_inode, zone_size, zone_shift = 0, zoff;
unsigned nrblocks;
int inode_offset, nrinodes, lct = 1, disk, fd, print = 0, file = 0;
int override = 0, simple = 0, dflag;
int donttest; /* skip test if it fits on medium */
long current_time, bin_time;
char zero[BLOCK_SIZE], *lastp;
char umap[(N_BLOCKS + 8) / 8]; /* bit map tells if block read yet */
int zone_map = 3; /* where is zone map? (depends on # inodes) */
FILE *proto;
char gwarning[] = {65, 46, 83, 46, 84, 97, 110, 101, 110, 98, 97, 117, 109, 10};
/*================================================================
* mkfs - make filesystem
*===============================================================*/
main(argc, argv)
int argc;
char *argv[];
{
int i, mode, usrid, grpid, badusage = 0;
unsigned zones, inodes;
unsigned long blocks;
char *token[MAX_TOKENS], line[LINE_LEN];
FILE *fopen();
long time(), ls;
struct stat statbuf;
/* Get two times, the current time and the mod time of the binary of
* mkfs itself. When the -d flag is used, the later time is put into
* the i_mtimes of all the files. This feature is useful when
* producing a set of file systems, and one wants all the times to be
* identical. First you set the time of the mkfs binary to what you
* want, then go. */
current_time = time(0L); /* time mkfs is being run */
stat(argv[0], &statbuf);
bin_time = statbuf.st_mtime; /* time when mkfs binary was last modified */
/* Process parameters and switches */
if (argc != 3 && argc != 4) badusage = 1;
if (stat(argv[argc - 1], &statbuf) == 0) {
if ((statbuf.st_mode & S_IFMT) != S_IFREG) badusage = 1;
}
if (badusage) {
write(2, "Usage: mkfs [-ldt] special proto\n", 33);
exit(1);
}
while (--argc) {
switch (argv[argc][0]) {
case '-':
while (*++argv[argc]) switch (*argv[argc]) {
case 'l':
case 'L': print = 1; break;
case 'o':
case 'O':
override = 1;
break;
case 'd':
case 'D':
current_time = bin_time;
dflag = 1;
break;
case 't':
case 'T':
donttest = 1;
break;
default:
printf("Bad switch %c, ignored.\n", *argv[argc]);
}
break;
default:
/* Process proto & special */
proto = fopen(argv[argc], "r");
if (proto != (FILE *) NULL) {
/* Prototype file is readable. */
getline(line, token); /* skip boot block info. */
/* Read the line with the block and inode counts. */
getline(line, token);
blocks = atol(token[0]);
if (blocks > N_BLOCKS)
pexit("Block count too large");
inodes = atoi(token[1]);
/* Process mode line for root directory. */
getline(line, token);
mode = mode_con(token[0]);
usrid = atoi(token[1]);
grpid = atoi(token[2]);
} else {
/* Maybe the prototype file is just a size.
* Check for that. */
blocks = atol(argv[argc]);
if (blocks < 4) pexit("Can't open prototype file");
if (blocks > N_BLOCKS)
pexit("Block count too large");
/* Ok, make simple file system of given size,
* using defaults. */
inodes = (blocks / 3) + 8; /* default is 3
* blocks/file */
mode = 040777;
usrid = BIN;
grpid = BINGRP;
simple = 1;
}
/* Open special */
argc--;
special(argv[argc]);
nrblocks = blocks;
nrinodes = inodes;
} /* end switch */
} /* end while */
#ifdef UNIX
if (!donttest) {
static short testb[BLOCK_SIZE / sizeof(short)];
/* Try writing the last block of partition or diskette. */
ls = lseek(fd, ((long) blocks - 1L) * BLOCK_SIZE, SEEK_SET);
testb[0] = 0x3245;
testb[1] = 0x11FF;
if (write(fd, (char *) testb, BLOCK_SIZE) != BLOCK_SIZE)
pexit("File system is too big for minor device");
sync(); /* flush write, so if error next read fails */
lseek(fd, ((long) blocks - 1L) * BLOCK_SIZE, SEEK_SET);
testb[0] = 0;
testb[1] = 0;
i = read(fd, (char *) testb, BLOCK_SIZE);
if (i != BLOCK_SIZE || testb[0] != 0x3245 || testb[1] != 0x11FF)
pexit("File system is too big for minor device");
lseek(fd, ((long) blocks - 1L) * BLOCK_SIZE, SEEK_SET);
testb[0] = 0;
testb[1] = 0;
if (write(fd, (char *) testb, BLOCK_SIZE) != BLOCK_SIZE)
pexit("File system is too big for minor device");
lseek(fd, 0L, SEEK_SET);
}
#endif
/* Make the file-system */
cache_init();
#if (MACHINE == ATARI)
if (isdev) {
char block0[BLOCK_SIZE];
get_block(0, block0);
/* need to read twice; first time gets an empty block */
get_block(0, block0);
/* zero parts of the boot block so the disk won't be recognized as
a tos disk any more. */
block0[0] = block0[1] = 0; /* branch code to boot code */
strncpy(&block0[2], "MINIX ", 6);
block0[16] = 0; /* number of FATS */
block0[17] = block0[18] = 0;/* number of dir entries */
block0[22] = block0[23] = 0;/* sectors/FAT */
bzero(&block0[30], 480); /* boot code */
put_block(0, block0);
}
else
#endif
put_block(0, zero); /* Write a null boot block. */
zone_shift = 0; /* for future use */
zones = nrblocks >> zone_shift;
super(zones, inodes);
i = alloc_inode(mode, usrid, grpid);
rootdir(i);
if (simple == 0) eat_dir(i);
if (print) print_fs();
flush();
exit(0);
} /* end main */
/*================================================================
* super - construct a superblock
*===============================================================*/
super(zones, inodes)
unsigned zones, inodes;
{
unsigned int i, inodeblks, initblks, initzones, nrzones;
unsigned int bit_map_len, b_needed, b_allocated, residual;
long zo;
struct super_block *sup;
char buf[BLOCK_SIZE], *cp;
sup = (struct super_block *) buf;
sup->s_ninodes = inodes;
sup->s_nzones = zones;
sup->s_imap_blocks = bitmapsize(1 + inodes);
sup->s_zmap_blocks = bitmapsize(zones);
inode_offset = sup->s_imap_blocks + sup->s_zmap_blocks + 2;
inodeblks = (inodes + INODES_PER_BLOCK - 1) / INODES_PER_BLOCK;
initblks = inode_offset + inodeblks;
initzones = (initblks + (1 << zone_shift) - 1) >> zone_shift;
nrzones = nrblocks >> zone_shift;
sup->s_firstdatazone = (initblks + (1 << zone_shift) - 1) >> zone_shift;
zoff = sup->s_firstdatazone - 1;
sup->s_log_zone_size = zone_shift;
sup->s_magic = SUPER_MAGIC; /* identify super blocks */
zo = 7L + (long) NR_INDIRECTS
+ (long) NR_INDIRECTS *NR_INDIRECTS;
sup->s_max_size = zo * BLOCK_SIZE;
zone_size = 1 << zone_shift; /* nr of blocks per zone */
for (cp = buf + sizeof(*sup); cp < &buf[BLOCK_SIZE]; cp++) *cp = 0;
put_block(1, buf);
/* Clear maps and inodes. */
fo